package org.alanlau.demo.thread;

import lombok.Data;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 *
 * @author liukun
 * @version 1.0
 * @date 2019/12/25 10:48
 */
@Configuration
@EnableAsync
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "thread-pool")
@Data
public class ThreadPoolConfig implements AsyncConfigurer {
    /**
     * Java虚拟机可用的CPU数量
     */
    private final int availableProcessor = Runtime.getRuntime().availableProcessors();
    /**
     * 核心线程数
     */
    private int corePoolSize = availableProcessor * 2 + 1;
    /**
     * 最大线程数
     */
    private int maxPoolSize = (availableProcessor * 2 + 1) * 2;
    /**
     * 线程队列容量
     */
    private int queueCapacity = 1000;
    /**
     * 线程存活时间
     */
    private int keepAliveSeconds = 60;
    /**
     * 线程名称前缀
     */
    private String threadNamePrefix = "CustomThread - ";

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new VisibleThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(corePoolSize);
        taskExecutor.setMaxPoolSize(maxPoolSize);
        taskExecutor.setQueueCapacity(queueCapacity);
        taskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        taskExecutor.setThreadNamePrefix(threadNamePrefix);
        // 设置拒绝策略，默认是 ThreadPoolExecutor.AbortPolicy()，丢弃任务并抛出异常
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
    }
}
